class h_card {

	async getStuCardDataFromOrigin(user) {
		const cardData = await this._getCardData(user)
		await this.redis.cache.set(`card@student@${user.userId}`, cardData, this.config.frame.sessionExpires.card)
		return cardData
	}

	async getTchCardDataFromOrigin(user) {
		const cardData = await this._getCardData(user)
		await this.redis.cache.set(`card@teacher@${user.userId}`, cardData, this.config.frame.sessionExpires.card)
		return cardData
	}

	async getCardDataByUserId(userId, ...fields) {
		if(!userId)
			return this.reject('-2020', 'user id invalid')
		const cardData = await this._getCardDataByUserId(userId, ...fields)
		return cardData
	}

	//更新学生一卡通数据
	async updateStuCardDataByUserId(userId, cardPwd, cardData) {
		try {
			if(!cardPwd || !cardData) 
				return
			const {cardNum, cardStatus, cardBalance, cardTranBalance, cardExpend, tradeList} = cardData
			const cardId = this.crypto.md5(cardNum)
			const result = await this.mysql.cxxy.select({
				table: 'card',
				field: 'cardId',
				where: 'cardId=$cardId',
				data: {
					cardId
				}
			})
			await this.mysql.cxxy.trans()
			if(!result[0]) {
				await this.mysql.cxxy.insert({
					table: 'card',
					field: [
						'cardId',
						'cardPwd',
						'cardNum',
						'cardStatus',
						'cardBalance',
						'cardTranBalance',
						'cardTradeList',
						'cardExpend',
						'tradeDate'
					],
					data: {
						cardId,
						cardPwd,
						cardNum,
						cardStatus,
						cardBalance,
						cardTranBalance,
						cardTradeList: JSON.stringify(tradeList),
						cardExpend,
						tradeDate: parseInt(Date.now() / 1000)
					}
				})
				await this.mysql.cxxy.update({
					table: 'student',
					field: 'stuSCardId=$stuSCardId',
					where: 'userId=$userId',
					data: {
						stuSCardId: cardId,
						userId
					}
				})
				await this.mysql.cxxy.cmt()
				return
			}
			await this.mysql.cxxy.update({
				table: 'card',
				field: [
					'cardPwd=$cardPwd',
					'cardStatus=$cardStatus',
					'cardBalance=$cardBalance',
					'cardTranBalance=$cardTranBalance',
					'cardTradeList=$cardTradeList',
					'cardExpend=$cardExpend',
					'tradeDate=$tradeDate'
				],
				where: 'cardId=$cardId',
				data: {
					cardPwd,
					cardStatus,
					cardBalance,
					cardTranBalance,
					cardTradeList: JSON.stringify(tradeList),
					cardExpend,
					tradeDate: parseInt(Date.now() / 1000),
					cardId
				}
			})
			await this.mysql.cxxy.cmt()
			return cardId
		}
		catch(err) {
			console.error(err)
			this.common.writeLog('error', `update student ${userId} card data failed`)
			return this.reject('-3038', 'update student card data failed')
		}
	}

	//更新教职工一卡通数据
	async updateTchCardDataByUserId(userId, cardPwd, cardData) {
		try {
			if(!cardPwd || !cardData) 
				return
			const {cardNum, cardStatus, cardBalance, cardTranBalance, cardExpend, tradeList} = cardData
			const cardId = this.crypto.md5(cardNum)
			const result = await this.mysql.cxxy.select({
				table: 'card',
				field: 'cardId',
				where: 'cardId=$cardId',
				data: {
					cardId
				}
			})
			await this.mysql.cxxy.trans()
			if(!result[0]) {
				await this.mysql.cxxy.insert({
					table: 'card',
					field: [
						'cardId',
						'cardPwd',
						'cardNum',
						'cardStatus',
						'cardBalance',
						'cardTranBalance',
						'cardTradeList',
						'cardExpend',
						'tradeDate'
					],
					data: {
						cardId,
						cardPwd,
						cardNum,
						cardStatus,
						cardBalance,
						cardTranBalance,
						cardTradeList: JSON.stringify(tradeList),
						cardExpend,
						tradeDate: parseInt(Date.now() / 1000)
					}
				})
				await this.mysql.cxxy.update({
					table: 'teacher',
					field: 'tchSCardId=$tchSCardId',
					where: 'userId=$userId',
					data: {
						tchSCardId: cardId,
						userId
					}
				})
				await this.mysql.cxxy.cmt()
				return
			}
			await this.mysql.cxxy.update({
				table: 'card',
				field: [
					'cardPwd=$cardPwd',
					'cardStatus=$cardStatus',
					'cardBalance=$cardBalance',
					'cardTranBalance=$cardTranBalance',
					'cardTradeList=$cardTradeList',
					'cardExpend=$cardExpend',
					'tradeDate=$tradeDate'
				],
				where: 'cardId=$cardId',
				data: {
					cardPwd,
					cardStatus,
					cardBalance,
					cardTranBalance,
					cardTradeList: JSON.stringify(tradeList),
					cardExpend,
					tradeDate: parseInt(Date.now() / 1000),
					cardId
				}
			})
			await this.mysql.cxxy.cmt()
			return cardId
		}
		catch(err) {
			console.error(err)
			this.common.writeLog('error', `update teacher ${userId} card data failed`)
			return this.reject('-3038', 'update teacher card data failed')
		}
	}

	async getStuCardCache(userId) {
		const cardData = await this.redis.cache.get(`card@student@${userId}`, true)
		if(cardData)
			return cardData
		return false
	}

	async getTchCardCache(userId) {
		const cardData = await this.redis.cache.get(`card@teacher@${userId}`, true)
		if(cardData)
			return cardData
		return false
	}

	async clearStuCardCache(userId) {
		await this.redis.cache.delete(`card@student@${userId}`)
	}

	async clearTchCardCache(userId) {
		await this.redis.cache.delete(`card@teacher@${userId}`)
	}

	//登录一卡通平台
	async cardLogin(userType = 0, userId, userPwd, user) {
		if(this._checkCardLogin(user, userId))
			return user
		const result = await this.common.reqPost({
			url: `${this.config.card.url}loginstudent.action`,
			headers: {
				'content-type': 'application/x-www-form-urlencoded',
				charset: 'UTF-8'
			},
			data: {
				name: userId,
				userType: [1][userType],
				passwd: userPwd,
				loginType: [2][userType]
			},
			getStatus: true,
			getCookie: true
		})
		const {status, data, cookie} = result
		if(status.code != 200 || /sdfsdfsdf\.jpg/.test(data)) {
			console.error(`card user ${userId} login failed`)
			await this._cardLogout(user)
			return this.reject('-3029', 'card user login failed')
		}
		const cardSession = cookie[0]['JSESSIONID']
		console.log(`card session is ${cardSession}`)
		user.data.card = {
			userId,
			userPwd,
			userType: userType,
			logined: true,
			session: cardSession,
			time: parseInt(Date.now() / 1000)
		}
		await this.common.updateSessionData(user.session, {
			card: user.data.card
		})
		return user
	}

	_checkCardLogin(user, userId) {
		console.log(user)
		if(!user.data || !user.data.card || !user.data.card.logined || !user.data.card.session || !user.data.card.time || (parseInt(Date.now() / 1000) - user.data.card.time) > this.config.frame.sessionExpires.card || (userId && userId != user.data.card.userId)) {
			console.error('card user not login')
			return false
		}
		console.log('card user logined')
		return true
	}

	async _cardLogout(user) {
		user.data.card = {
			userId: undefined,
			logined: false,
			session: undefined,
			time: 0
		}
		//清除一卡通用户数据缓存
		await this.redis.user.delete(`card@${user.userId}`)
		await this.common.updateSessionData(user.session, {
			card: user.data.card
		})
	}

	async _getCardDataByUserId(userId, ...fields) {
		let cardData = await this.redis.user.get(`card@${userId}`, true)
		if(!cardData) {
			cardData = await this.mysql.cxxy.select({
				table: ['student s', 'card c'],
				field: fields || 'userId',
				where: 's.stuSCardId=c.cardId && s.userId=$userId',
				data: {
					userId
				}
			})
			cardData = cardData[0]
		}
		else {
			const keys = Object.keys(cardData)
			const fieldsArr = !fields ? [] : fields
			const noFields = fieldsArr.filter((key) => {
				return keys.indexOf(this.common.trim(key)) == -1
			})
			if(noFields.length != 0) {
				const temp = await this.mysql.cxxy.select({
					table: ['student s', 'card c'],
					field: noFields,
					where: 's.stuSCardId=c.cardId && s.userId=$userId',
					data: {
						userId
					}
				})
				if(temp[0])
					Object.assign(cardData, temp[0])
			}
		}
		if(cardData)
			await this.redis.user.set(`card@${userId}`, cardData, this.config.frame.sessionExpires.card)
		return cardData ? cardData : null
	}

	async _getCardData(user) {
		if(!this._checkCardLogin(user))
			return this.reject('-3030', 'card user not logined in')
		const {userId, userPwd, session} = user.data.card
		const reject = (code, msg) => {throw {code, msg}}
		let cardExpend = 0
		//获取卡号和余额信息
		const result = await this.common.reqGet({
			url: `${this.config.card.url}accountcardUser.action`,
			headers: {
				Cookie: `JSESSIONID=${session}; path=/;`
			},
			getStatus: true
		})
		let {status, data} = result
		if(status.code != 200) {
			await this._cardLogout(user)
			return this.reject('-3033', 'get card data failed')
		}
		let $
		try {
			$ = this.common.parseHTML(data, false)
			data = $('.tttt tbody tr th table tbody tr')
		}
		catch(err) {
			await this._cardLogout(user)
			return this.reject('-3033', 'get card data failed')
		}
		console.log(data.eq(11).children('td').html())
		const cardNum = data.eq(1).children('td').eq(3).text().trim()
		const cardStatus = ['正常', '冻结'].indexOf(data.eq(11).children('td').eq(5).text().trim())
		const moneyResult = data.eq(12).children('td').eq(1).text().match(/(.*)元（卡余额）(.*)元\(当前过渡余额\)(.*)元\(上次过渡余额\)/)
		if(!moneyResult || !moneyResult[1])
			return this.reject('-3031', 'card money data not found')
		//余额 当前过渡余额 下次过渡余额
		let [, cardBalance, nowTranBalance, lastTranBalance] = moneyResult
		console.log(`cardNum is ${cardNum} , card status is ${cardStatus}, balance is ${cardBalance}`)
		if(isNaN(cardBalance.trim()))
			return this.reject('-3032', 'card money parse failed')
		cardBalance = parseInt(parseFloat(cardBalance) * 100)
		nowTranBalance = parseInt(parseFloat(nowTranBalance) * 100) || 0
		const result2 = await this.common.reqPost({
			url: `${this.config.card.url}accounttodatTrjnObject.action`,
			headers: {
				'content-type': 'application/x-www-form-urlencoded',
				Cookie: `JSESSIONID=${session}; path=/;`
			},
			data: {
				account: cardNum,
				inputObject: 'all',
				Submit: '+%C8%B7+%B6%A8+'
			},
			getBuffer: true,
			getStatus: true
		})
		const {status: status2, data: buffer2} = result2
		const data2 = this.common.iconv.decode(buffer2, 'GBK')
		if(status2.code != 200) {
			await this._cardLogout(user)
			return this.reject('-3033', 'get card data failed')
		}
		$ = this.common.parseHTML(data2, false)
		let todayTradeList = []
		const list1 = $('#tables tbody tr')
		list1.each(function(index) {
			if(index == 0 || index == list1.length - 1)
				return
			const item = $(this).children('td')
			const tradeMoney = Math.abs(parseFloat(item.eq(5).text())) * 100
			const tradeData = {
				tradeTime: parseInt((new Date(item.eq(0).text().trim())).getTime() / 1000),
				tradeType: item.eq(3).text().trim() ? ['持卡人消费', '存款'].indexOf(item.eq(3).text().trim()) : 0,
				tradeSite: item.eq(4).text().trim() ? item.eq(4).text().trim() : '卡务中心',
				tradeMoney,
				cardBalance: parseFloat(item.eq(6).text()) * 100,
				cardStatus: ['正常', '冻结'].indexOf(item.eq(8).text().trim())
			}
			cardExpend += tradeMoney
			todayTradeList.push(tradeData)
		})
		console.log('today trade list is ', todayTradeList)
		const result3 = await this.common.reqPost({
			url: `${this.config.card.url}accounthisTrjn1.action`,
			headers: {
				'content-type': 'application/x-www-form-urlencoded',
				Cookie: `JSESSIONID=${session}; path=/;`
			},
			data: {
				account: cardNum,
				inputObject: 'all',
				Submit: '+%C8%B7+%B6%A8+'
			},
			getStatus: true
		})
		const {status: status3, data: data3} = result3
		if(status3.code != 200) {
			await this._cardLogout(user)
			return this.reject('-3033', 'get card data failed')
		}
		const date = new Date()
		const dateStr = `${date.getFullYear()}${date.getMonth() + 1 > 9 ?(date.getMonth() + 1):('0' + (date.getMonth() + 1))}`
		const result4 = await this.common.reqPost({
			url: `${this.config.card.url}accounthisTrjn2.action`,
			headers: {
				'content-type': 'application/x-www-form-urlencoded',
				Cookie: `JSESSIONID=${session}; path=/;`,
			},
			data: {
				inputStartDate: `${dateStr}01`,
				inputEndDate: `${dateStr}${date.getDate() > 9 ? date.getDate() : '0' + date.getDate()}`
			},
			getStatus: true
		})
		const {status: status4, data: data4} = result4
		if(status4.code != 200) {
			await this._cardLogout(user)
			return this.reject('-3033', 'get card data failed')
		}
		let monthTradeList = []
		let pageCount = 1
		let pageIndex = 0
		while(pageIndex != pageCount) {
			pageIndex++
			let result5
			if(pageIndex == 1) {
				result5 = await this.common.reqPost({
					url: `${this.config.card.url}accounthisTrjn3.action`,
					headers: {
						'content-type': 'application/x-www-form-urlencoded',
						Cookie: `JSESSIONID=${session}; path=/;`,
					},
					data: {},
					getBuffer: true,
					getStatus: true
				})
			}
			else {
				result5 = await this.common.reqPost({
					url: `${this.config.card.url}accountconsubBrows.action`,
					headers: {
						'content-type': 'application/x-www-form-urlencoded',
						Cookie: `JSESSIONID=${session}; path=/;`,
					},
					data: {
						pageNum: pageIndex
					},
					getBuffer: true,
					getStatus: true
				})
			}
			const {status: status5, data: buffer5} = result5
			const data5 = this.common.iconv.decode(buffer5, 'GBK')
			if(status5.code != 200) {
				await this._cardLogout(user)
				return this.reject('-3033', 'get card data failed')
			}
			$ = this.common.parseHTML(data5, false)
			const list2 = $('#tables tbody tr')
			list2.each(function(index) {
				if(index == 0)
					return
				const item = $(this).children('td')
				if(index == list2.length - 1) {
					const str = item.children('div').eq(0).text()
					const temp = str.match(/共(\d+)页/)
					const temp2 = str.match(/第(\d+)页/)
					if(!temp[1] || !temp2[1] || isNaN(temp[1]) || isNaN(temp2[1]))
						reject('-3034', 'card page data invalid')
					console.log(temp[1], temp2[1])
					pageCount = temp[1]
					if(pageCount == 0)
						pageIndex = 0
					return
				}
				const tradeMoney = Math.abs(parseFloat(item.eq(5).text())) * 100
				const tradeData = {
					tradeTime: parseInt((new Date(item.eq(0).text().trim())).getTime() / 1000),
					tradeType: item.eq(3).text().trim() ? ['持卡人消费', '存款'].indexOf(item.eq(3).text().trim()) : 0,
					tradeSite: item.eq(4).text().trim() ? item.eq(4).text().trim() : '卡务中心',
					tradeMoney,
					cardBalance: parseInt(parseFloat(item.eq(6).text()) * 100),
					cardStatus: ['正常', '冻结'].indexOf(item.eq(8).text().trim())
				}
				cardExpend += tradeMoney
				monthTradeList.push(tradeData)
			})
		}
		console.log('month trade list is', monthTradeList)
		const cardData = {
			cardNum,
			cardStatus,
			cardBalance,
			cardTranBalance: nowTranBalance,
			cardExpend,
			tradeList: todayTradeList.concat(monthTradeList)
		}
		return cardData
	}

}

module.exports = h_card